package qq

import (
	"encoding/json"
	"github.com/crozz-net/gopenapi/qq/model"
	"github.com/crozz-net/gopenapi/request"
	"net/url"
	"regexp"
	"strings"
)

const BASE_URL = "https://graph.qq.com/"

type QQ struct {
	Client_id     string
	Client_secret string
	Redirect_uri  string
	User          api_user
	T             api_t
	Relation      api_relation
}

func NewQQ(client_id, client_secret, redirect_uri string) *QQ {
	return &QQ{
		Client_id:     client_id,
		Client_secret: client_secret,
		Redirect_uri:  redirect_uri,
		User:          api_user{client_id: client_id},
		T:             api_t{client_id: client_id},
		Relation:      api_relation{client_id: client_id},
	}
}

/**
 * 获取Authorization Code<br/>
 * 文档地址：http://wiki.connect.qq.com/使用authorization_code获取access_token
 *
 * @param client_id    必须，申请QQ登录成功后，分配给应用的appid。
 * @param redirect_uri 必须，成功授权后的回调地址，必须是注册appid时填写的主域名下的地址，建议设置为网站首页或网站的用户中心。注意需要将url进行URLEncode。
 * @param state        必须，client端的状态值。用于第三方应用防止CSRF攻击，成功授权后回调时会原样带回。请务必严格按照流程检查用户与state参数状态的绑定。
 * @param scope        可选，请求用户授权时向用户显示的可进行授权的列表
 * @param display      可选，仅PC网站接入时使用。用于展示的样式。不传则默认展示为PC下的样式。如果传入“mobile”，则展示为mobile端下的样式。
 * @param gut          仅WAP网站接入时使用。QQ登录页面版本（1：wml版本； 2：xhtml版本），默认值为1。
 * @param wap          是否使wap版，默认为false
 */
func (this *QQ) Authorize(state, display, scope, gut string, wap bool) string {
	param := url.Values{}
	param.Add("client_id", this.Client_id)
	param.Add("redirect_uri", this.Redirect_uri)
	param.Add("response_type", "code")
	param.Add("state", state)
	param.Add("display", display)
	param.Add("scope", scope)

	base := "https://graph.qq.com/oauth2.0/authorize"
	if wap {
		param.Add("gut", gut)
		base = "https://graph.z.qq.com/moc2/authorize"
	}

	return base + param.Encode()
}

/**
 * 通过Authorization Code获取Access Token<br/>
 * 权限自动续期<br/>
 * 文档地址：http://wiki.connect.qq.com/使用authorization_code获取access_token<br/>
 * Step2：通过Authorization Code获取Access Token<br/>
 * Step3：（可选）权限自动续期，获取Access Token<br/>
 *
 * @param client_id     申请QQ登录成功后，分配给网站的appid。
 * @param client_secret 申请QQ登录成功后，分配给网站的appkey。
 * @param grant_type    授权类型，“authorization_code”或“refresh_token”。
 * @param code          上一步返回的authorization code。如果用户成功登录并授权，则会跳转到指定的回调地址，并在URL中带上Authorization
 *                      Code。注意此code会在10分钟内过期。
 * @param refresh_token {@link Resp_token}中的refresToken。
 * @param redirect_uri  与上面一步中传入的redirect_uri保持一致。
 * @param wap           是否使wap版，默认为false
 */
func (this *QQ) Token(grant_type, code, refresh_token string, wap bool) (*model.Resp_token, error) {
	param := url.Values{}
	param.Add("client_id", this.Client_id)
	param.Add("client_secret", this.Client_secret)
	param.Add("redirect_uri", this.Redirect_uri)
	param.Add("grant_type", grant_type)
	param.Add("code", code)
	param.Add("refresh_token", refresh_token)

	base := "https://graph.qq.com/oauth2.0/token"
	if wap {
		base = "https://graph.z.qq.com/moc2/token"
	}

	resp_token := &model.Resp_token{}
	err := request.HttpGetAsObj(base, param, resp_token)

	return resp_token, err
}

func (this *QQ) Me(access_token string, wap bool) (*model.Resp_me, error) {
	param := url.Values{}
	param.Add("access_token", access_token)

	base := "https://graph.qq.com/oauth2.0/me"
	if wap {
		base = "https://graph.z.qq.com/moc2/me"
	}

	resp_me := &model.Resp_me{}

	if bs, err := request.HttpGet(base, param); err != nil {
		return nil, err
	} else {
		str := string(bs)
		if strings.Index(str, "callback") > -1 {
			reg := regexp.MustCompile(`\{.*\}`)
			str = reg.FindAllString(str, -1)[0]
		}
		json.Unmarshal([]byte(str), resp_me)
	}

	return resp_me, nil
}
